import json
import numpy as np


def read_log_file(log_file):
    process_a_start_time = {}
    process_a_end_time = {}
    process_b_start_time = {}
    process_b_end_time = {}

    with open(log_file, 'r') as file:
        for line in file:
            if "static_multistream" in line:
                parts = line.strip().split('|')
                frame_id = parts[1].split(':')[1]
                event = parts[4].split(':')
                process = event[0]
                action = event[1]
                timestamp = float(event[2])

                if process == 'ProcessA':
                    if action == 'start':
                        process_a_start_time[frame_id] = timestamp
                    elif action == 'end':
                        process_a_end_time[frame_id] = timestamp
                elif process == 'ProcessB':
                    if action == 'start':
                        process_b_start_time[frame_id] = timestamp
                    elif action == 'end':
                        process_b_end_time[frame_id] = timestamp

    return process_a_start_time, process_a_end_time, process_b_start_time, process_b_end_time


def calculate_metrics(process_a_start_time, process_a_end_time, process_b_start_time, process_b_end_time):
    process_a_durations = []
    process_b_durations = []
    frame_durations = []
    start_times = []
    end_times = []

    for frame in process_a_start_time:
        if frame in process_a_end_time and frame in process_b_start_time and frame in process_b_end_time:
            process_a_duration = process_a_end_time[frame] - process_a_start_time[frame]
            process_b_duration = process_b_end_time[frame] - process_b_start_time[frame]
            frame_duration = process_b_end_time[frame] - process_a_start_time[frame]

            process_a_durations.append(process_a_duration)
            process_b_durations.append(process_b_duration)
            frame_durations.append(frame_duration)
            start_times.append(process_a_start_time[frame])
            end_times.append(process_b_end_time[frame])

    return process_a_durations, process_b_durations, frame_durations, start_times, end_times


def get_percentiles(data, percentiles):
    return {f'P{int(p * 100)}': np.percentile(data, p * 100) for p in percentiles}


def calculate_throughput(start_times, end_times):
    total_time = max(end_times) - min(start_times)
    frame_count = len(start_times)
    throughput = frame_count / (total_time / 1000)  # frames per second
    return throughput, frame_count, total_time


def save_results(results, output_file):
    with open(output_file, 'w') as file:
        json.dump(results, file, ensure_ascii=False, indent=4)


if __name__ == "__main__":
    log_file = 'trace_analysis.log'
    result_file = 'result.json'

    process_a_start_time, process_a_end_time, process_b_start_time, process_b_end_time = read_log_file(log_file)
    process_a_durations, process_b_durations, frame_durations, start_times, end_times = calculate_metrics(
        process_a_start_time, process_a_end_time, process_b_start_time, process_b_end_time)

    results = {
        'ProcessA': {
            'average_duration': np.mean(process_a_durations),
            'P99_duration': np.percentile(process_a_durations, 99),
            'P90_duration': np.percentile(process_a_durations, 90)
        },
        'ProcessB': {
            'average_duration': np.mean(process_b_durations),
            'P99_duration': np.percentile(process_b_durations, 99),
            'P90_duration': np.percentile(process_b_durations, 90)
        },
        'throughput': calculate_throughput(start_times, end_times)[0],
        'average_frame_duration': np.mean(frame_durations),
        'frame_duration_percentiles': get_percentiles(frame_durations, [0.9, 0.99])
    }

    frame_infos = []
    for frame in process_a_start_time:
        if frame in process_a_end_time and frame in process_b_start_time and frame in process_b_end_time:
            frame_info = (
                f"帧号{frame}，ProcessA工序耗时为：（{process_a_end_time[frame]} - {process_a_start_time[frame]}），"
                f"ProcessB工序耗时为：（{process_b_end_time[frame]} - {process_b_start_time[frame]}）， "
                f"该帧整体耗时为：（{process_b_end_time[frame]} - {process_a_start_time[frame]}）"
            )
            frame_infos.append(frame_info)
    results['frame_infos'] = frame_infos

    save_results(results, result_file)


